package com.wxscrmplus.marketing.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.wxscrmplus.common.core.domain.entity.SysUser;
import com.wxscrmplus.common.exception.ServiceException;
import com.wxscrmplus.common.utils.StreamUtils;
import com.wxscrmplus.common.utils.StringUtils;
import com.wxscrmplus.common.core.page.TableDataInfo;
import com.wxscrmplus.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.wxscrmplus.customer.domain.Customer;
import com.wxscrmplus.customer.mapper.CustomerMapper;
import com.wxscrmplus.marketing.domain.MarBatchSendMsgCustomer;
import com.wxscrmplus.marketing.domain.MarMsgAttachments;
import com.wxscrmplus.marketing.mapper.MarBatchSendMsgCustomerMapper;
import com.wxscrmplus.marketing.mapper.MarCategoryMapper;
import com.wxscrmplus.marketing.mapper.MarMsgAttachmentsMapper;
import com.wxscrmplus.system.mapper.SysUserMapper;
import com.wxscrmplus.wxcp.factory.WxCpServiceFactory;
import com.wxscrmplus.marketing.domain.MarBatchSendMsg;
import com.wxscrmplus.marketing.domain.bo.MarBatchSendMsgBo;
import com.wxscrmplus.marketing.domain.vo.MarBatchSendMsgVo;
import com.wxscrmplus.marketing.mapper.MarBatchSendMsgMapper;
import com.wxscrmplus.marketing.service.IMarBatchSendMsgService;
import lombok.RequiredArgsConstructor;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpExternalContactService;
import me.chanjar.weixin.cp.bean.external.WxCpMsgTemplate;
import me.chanjar.weixin.cp.bean.external.WxCpMsgTemplateAddResult;
import me.chanjar.weixin.cp.bean.external.msg.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 群发消息Service业务层处理
 *
 * @author 王永超
 * @date 2023-05-11
 */
@RequiredArgsConstructor
@Service
public class MarBatchSendMsgServiceImpl extends WxCpServiceFactory implements IMarBatchSendMsgService {


    private final MarBatchSendMsgMapper baseMapper;
    private final MarCategoryMapper categoryMapper;
    private final SysUserMapper userMapper;
    private final MarMsgAttachmentsMapper marMsgAttachmentsMapper;
    private final CustomerMapper customerMapper;
    private final MarBatchSendMsgCustomerMapper batchSendMsgCustomerMapper;

    /**
     * 发送群发消息
     */
    @Override
    public void send(Long batchSendMsgId) {
        MarBatchSendMsg marBatchSendMsg = baseMapper.selectById(batchSendMsgId);
        List<MarMsgAttachments> welcomeAttachmentsList = marMsgAttachmentsMapper.selectList(Wrappers.query(new MarMsgAttachments()).lambda()
            .eq(MarMsgAttachments::getTargetType, MarMsgAttachments.TargetTypeFieldEnums.TWO.getValue())
            .eq(MarMsgAttachments::getTargetId, marBatchSendMsg.getBatchSendMsgId()));
        List<Attachment> attachmentList = new ArrayList<>();
        for (MarMsgAttachments marWelcomeAttachments : welcomeAttachmentsList) {
            Attachment attachment = new Attachment();
            JSONObject attContent = marWelcomeAttachments.getAttContent();
            switch (marWelcomeAttachments.getMsgtype()) {
                case WxConsts.MediaFileType.IMAGE:
                    if (ObjectUtil.isNotNull(attContent.get("mediaId"))) {
                        Image image = new Image();
                        image.setMediaId(attContent.getStr("mediaId"));
                        attachment.setImage(image);
                        attachmentList.add(attachment);
                    }
                    break;
                case WxConsts.MediaFileType.VIDEO:
                    if (ObjectUtil.isNotNull(attContent.get("mediaId"))) {
                        Video video = new Video();
                        video.setMediaId(attContent.getStr("mediaId"));
                        attachment.setVideo(video);
                        attachmentList.add(attachment);
                    }
                    break;
                case WxConsts.MediaFileType.FILE:
                    if (ObjectUtil.isNotNull(attContent.get("mediaId"))) {
                        File file = new File();
                        file.setMediaId(attContent.getStr("mediaId"));
                        attachment.setFile(file);
                        attachmentList.add(attachment);
                    }
                    break;
                case "link":
                    Link link = new Link();
                    link.setTitle(attContent.getStr("title"));
                    link.setDesc(attContent.getStr("desc"));
                    link.setUrl(attContent.getStr("url"));
                    link.setPicUrl(attContent.getStr("picurl"));
                    attachment.setLink(link);
                    attachmentList.add(attachment);
                    break;
            }
        }

        WxCpExternalContactService externalContactService = getExternalContactService();
        WxCpMsgTemplate wxCpMsgTemplate = new WxCpMsgTemplate();
        SysUser sysUser = userMapper.selectById(marBatchSendMsg.getUserId());
        wxCpMsgTemplate.setSender(sysUser.getUserName());
        Text text = new Text();
        text.setContent(marBatchSendMsg.getMessageText());
        wxCpMsgTemplate.setText(text);
        wxCpMsgTemplate.setChatType(marBatchSendMsg.getChatType());
        wxCpMsgTemplate.setAttachments(attachmentList);
        if (marBatchSendMsg.getChatType().equals(MarBatchSendMsg.ChatTypeFieldEnums.ONE.getValue())) {
            List<MarBatchSendMsgCustomer> marBatchSendMsgCustomerList = batchSendMsgCustomerMapper.selectList(Wrappers.query(new MarBatchSendMsgCustomer())
                .lambda().eq(MarBatchSendMsgCustomer::getBatchSendMsgId, batchSendMsgId));
            List<Long> customerIds = StreamUtils.toList(marBatchSendMsgCustomerList, MarBatchSendMsgCustomer::getCustomerId);
            List<Customer> customerList = customerMapper.selectBatchIds(customerIds);
            List<String> qwExternalUserids = StreamUtils.toList(customerList, Customer::getQwExternalUserid);
            wxCpMsgTemplate.setExternalUserid(qwExternalUserids);
        }
        wxCpMsgTemplate.setAttachments(attachmentList);
        WxCpMsgTemplateAddResult wxCpMsgTemplateAddResult = null;
        try {
            wxCpMsgTemplateAddResult = externalContactService.addMsgTemplate(wxCpMsgTemplate);
        } catch (WxErrorException e) {
            JSONObject jsonObject = JSONUtil.toBean(e.getError().getJson(), JSONObject.class);
            if (jsonObject.getStr("errcode").equals("40096")) {
                JSONArray failList = jsonObject.getJSONArray("fail_list");
                List<String> fail_list = new ArrayList<>();
                for (Object id : failList) {
                    fail_list.add(id.toString());
                }
                List<Customer> customerList = customerMapper.selectList(Wrappers.query(new Customer()).lambda()
                    .in(Customer::getQwExternalUserid, fail_list));
                throw new ServiceException(String.join(",", "无效目标客户" + StreamUtils.toList(customerList, Customer::getName)));

            }
            throw new RuntimeException(e);
        }
        marBatchSendMsg.setMsgid(wxCpMsgTemplateAddResult.getMsgId());
        marBatchSendMsg.setFailList(JSONUtil.toJsonStr(wxCpMsgTemplateAddResult.getFailList()));
        baseMapper.updateById(marBatchSendMsg);
    }

    /**
     * 查询群发消息
     */
    @Override
    public MarBatchSendMsgVo queryById(Long batchSendMsgId) {
        MarBatchSendMsgVo marBatchSendMsgVo = baseMapper.selectVoById(batchSendMsgId);
        marBatchSendMsgVo.setCategoryLabel(categoryMapper.findNameById(marBatchSendMsgVo.getCategoryId()));
        List<MarBatchSendMsgCustomer> marBatchSendMsgCustomerList = batchSendMsgCustomerMapper.selectList(Wrappers.query(new MarBatchSendMsgCustomer())
            .lambda().eq(MarBatchSendMsgCustomer::getBatchSendMsgId, batchSendMsgId));
        marBatchSendMsgVo.setCustomerIds(StreamUtils.toList(marBatchSendMsgCustomerList, MarBatchSendMsgCustomer::getCustomerId));
        return marBatchSendMsgVo;
    }

    /**
     * 查询群发消息列表
     */
    @Override
    public TableDataInfo<MarBatchSendMsgVo> queryPageList(MarBatchSendMsgBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<MarBatchSendMsg> lqw = buildQueryWrapper(bo);
        Page<MarBatchSendMsgVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        List<MarBatchSendMsgVo> records = result.getRecords();
        for (MarBatchSendMsgVo record : records) {
            record.setCategoryLabel(categoryMapper.findNameById(record.getCategoryId()));
            record.setUserLabel(userMapper.findNickNameById(record.getUserId()));
        }
        return TableDataInfo.build(result);
    }

    /**
     * 查询群发消息列表
     */
    @Override
    public List<MarBatchSendMsgVo> queryList(MarBatchSendMsgBo bo) {
        LambdaQueryWrapper<MarBatchSendMsg> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<MarBatchSendMsg> buildQueryWrapper(MarBatchSendMsgBo bo) {
// 90750eb6897e3e5d8975b6b0df2f754c
        Set<Long> categoryIdList = new HashSet<>();
        if (ObjectUtil.isNotNull(bo.getCategoryId())) {
            categoryIdList.add(bo.getCategoryId());
        }
        if (CollUtil.isNotEmpty(bo.getCategoryIdList())) {
            categoryIdList.addAll(bo.getCategoryIdList());
        }
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<MarBatchSendMsg> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getChatType()), MarBatchSendMsg::getChatType, bo.getChatType());
        lqw.like(StringUtils.isNotBlank(bo.getMessageText()), MarBatchSendMsg::getMessageText, bo.getMessageText());
        lqw.eq(bo.getAllowSelect() != null, MarBatchSendMsg::getAllowSelect, bo.getAllowSelect());
        lqw.eq(bo.getCategoryId() != null, MarBatchSendMsg::getCategoryId, bo.getCategoryId());
        lqw.in(CollUtil.isNotEmpty(categoryIdList), MarBatchSendMsg::getCategoryId, categoryIdList);
        lqw.in(CollUtil.isNotEmpty(bo.getDataRangeUserIds()), MarBatchSendMsg::getUserId, bo.getDataRangeUserIds());
        lqw.orderByDesc(MarBatchSendMsg::getBatchSendMsgId);
        return lqw;
    }

    /**
     * 新增群发消息
     */
    @Transactional
    @Override
    public Boolean insertByBo(MarBatchSendMsgBo bo) {
        MarBatchSendMsg add = BeanUtil.toBean(bo, MarBatchSendMsg.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setBatchSendMsgId(add.getBatchSendMsgId());
        }
        if (add.getChatType().equals(MarBatchSendMsg.ChatTypeFieldEnums.ONE.getValue())) {
            List<Long> customerIds = bo.getCustomerIds();
            List<MarBatchSendMsgCustomer> marBatchSendMsgCustomerList = new ArrayList<>();
            for (Long customerId : customerIds) {
                MarBatchSendMsgCustomer marBatchSendMsgCustomer = new MarBatchSendMsgCustomer();
                marBatchSendMsgCustomer.setBatchSendMsgId(add.getBatchSendMsgId());
                marBatchSendMsgCustomer.setCustomerId(customerId);
                marBatchSendMsgCustomerList.add(marBatchSendMsgCustomer);
            }
            batchSendMsgCustomerMapper.insertBatch(marBatchSendMsgCustomerList);
        }
        return flag;
    }

    /**
     * 修改群发消息
     */
    @Transactional
    @Override
    public Boolean updateByBo(MarBatchSendMsgBo bo) {
        MarBatchSendMsg update = BeanUtil.toBean(bo, MarBatchSendMsg.class);
        validEntityBeforeSave(update);
        batchSendMsgCustomerMapper.delete(Wrappers.query(new MarBatchSendMsgCustomer()).lambda()
            .eq(MarBatchSendMsgCustomer::getBatchSendMsgId, bo.getBatchSendMsgId()));
        if (update.getChatType().equals(MarBatchSendMsg.ChatTypeFieldEnums.ONE.getValue())) {
            List<Long> customerIds = bo.getCustomerIds();
            List<MarBatchSendMsgCustomer> marBatchSendMsgCustomerList = new ArrayList<>();
            for (Long customerId : customerIds) {
                MarBatchSendMsgCustomer marBatchSendMsgCustomer = new MarBatchSendMsgCustomer();
                marBatchSendMsgCustomer.setBatchSendMsgId(bo.getBatchSendMsgId());
                marBatchSendMsgCustomer.setCustomerId(customerId);
                marBatchSendMsgCustomerList.add(marBatchSendMsgCustomer);
            }
            batchSendMsgCustomerMapper.insertBatch(marBatchSendMsgCustomerList);
        }
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(MarBatchSendMsg entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除群发消息
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }
}
